package com.uu.safeguard.aop;

import com.alibaba.fastjson.JSON;
import com.uu.safeguard.common.OperLogConst;
import com.uu.safeguard.entity.OperationLog;
import com.uu.safeguard.result.Result;
import com.uu.safeguard.service.MemberService;
import com.uu.safeguard.service.OperationLogService;
import com.uu.safeguard.utils.CommonUtil;
import com.uu.safeguard.utils.JwtUtil;
import net.sf.json.JSONObject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @title: OperationAspect
 * @description: 操作日志切面处理类
 */
@Aspect
@Component
public class OperationLogAspect {
    private Logger logger = LoggerFactory.getLogger(OperationLogAspect.class);

    @Resource
    OperationLogService operationLogService;

    @Resource
    MemberService memberService;

    /**
     * 设置操作日志切入点   在注解的位置切入代码
     */
    @Pointcut("@annotation(com.uu.safeguard.aop.OperationLogAnnotation)")
    public void operLogPoinCut() {
    }


    @AfterReturning(returning  /**
     * 记录操作日志
     * @param joinPoint 方法的执行点
     * @param result  方法返回值
     * @throws Throwable
     */ = "result", value = "operLogPoinCut()")
    public void saveOperLog(JoinPoint joinPoint, Object result) throws Throwable {
        // 获取RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        // 从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
        try {
            //将返回值转换成map集合
            Map<String, String[]> parameterMap = request.getParameterMap();
            Result newResult = (Result) result;
            OperationLog operationLog = new OperationLog();
            // 从切面织入点处通过反射机制获取织入点处的方法
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            //获取切入点所在的方法
            Method method = signature.getMethod();
            //获取操作
            OperationLogAnnotation annotation = method.getAnnotation(OperationLogAnnotation.class);
            if (annotation != null) {
                operationLog.setModel(annotation.operModul());
                operationLog.setAction(annotation.operAction());
                operationLog.setDescription(annotation.operDesc());
            }
            //平台类型
            operationLog.setType(OperLogConst.SAFEGUARD_PLATFORM);
            //请求的url
            operationLog.setAccessUrl(request.getServletPath());
            //操作时间
            operationLog.setCreateTime(System.currentTimeMillis());
            operationLog.setUpdateTime(System.currentTimeMillis());
            //token sn
            operationLog.setActionMemberSn(JwtUtil.getUserId(request.getHeader("token")));
            //通过 tokenSn 查找用户平台及运营商
            LinkedHashMap<String, Object> member = memberService.findMemberBySn(JwtUtil.getUserId(request.getHeader("token")));
            //运营商账号
            operationLog.setOperatorMemberSn(request.getHeader("operatorMemberSn")== null ? "": request.getHeader("operatorMemberSn"));
            //平台
            operationLog.setPlatformSn(request.getHeader("platformSn")== null ? member.get("platform_sn").toString(): request.getHeader("platformSn"));
            //请求的参数
            operationLog.setRequestData(JSON.toJSONString(parameterMap));
            //操作IP
            operationLog.setLoginIp(CommonUtil.getIpAddr());
            //返回值信息
            operationLog.setReturnData(JSONObject.fromObject(newResult).toString());
            //保存日志
            operationLogService.insert(operationLog);

        } catch (Exception e) {
            e.printStackTrace();
            logger.info("Log Error:"+e.getMessage());
        }
    }

}
